package com.codingfly.handler;

import com.codingfly.core.exception.AuthenticationException;
import com.codingfly.core.exception.BizException;
import com.codingfly.core.exception.UnauthorizedException;
import com.codingfly.model.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.ResourceAccessException;

import java.io.IOException;
import java.io.Serializable;
import java.util.List;

@RestController
@ControllerAdvice
public class GlobalExceptionHandler implements Serializable {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);


    @ExceptionHandler(BizException.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public Result handleBizException(BizException e) {
        logger.error(e.getMessage(), e);
        return Result.fail(500, e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result handleException(Exception e) {
        logger.error(e.getMessage(), e);
        return Result.fail(499, e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result handleMethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        logger.error(e.getMessage());
        BindingResult bindingResult = e.getBindingResult();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        for (FieldError fieldError : fieldErrors) {
            return Result.fail(500, fieldError.getDefaultMessage());
        }
        return Result.fail(500, null);
    }

    @ExceptionHandler(HttpMessageConversionException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result handleHttpMessageConversionException(HttpMessageConversionException e) {
        logger.error("请求参数格式错误，"+e.getMessage());
        return Result.fail(500, "请求参数格式错误，"+e.getMessage());
    }

    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result handleRuntimeException(RuntimeException e) {
        logger.error(e.getMessage(), e);
        return Result.fail(500, e.getMessage());
    }

    @ResponseStatus(value = HttpStatus.OK)
    @ExceptionHandler(ResourceAccessException.class)
    public Result handleResourceAccessException(ResourceAccessException e) {
        logger.error(e.getMessage(), e);
        return Result.fail(403, e.getMessage());
    }

    @ResponseStatus(value = HttpStatus.OK)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result handleMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        logger.error(e.getMessage(), e);
        return Result.fail(500, e.getMessage());
    }

    @ResponseStatus(value = HttpStatus.OK)
    @ExceptionHandler(ServletRequestBindingException.class)
    public Result handleServletRequestBindingException(ServletRequestBindingException e) {
        logger.error(e.getMessage(), e);
        return Result.fail(500, e.getMessage());
    }

    @ResponseStatus(value = HttpStatus.OK)
    @ExceptionHandler(IOException.class)
    public Result handleIOException(IOException e) {
        logger.error(e.getMessage(), e);
        return Result.fail(500, e.getMessage());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result handleIllegalArgumentException(IllegalArgumentException e) {
        logger.error(e.getMessage(), e);
        return Result.fail(500, e.getMessage());
    }

    /**
     * 未认证异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(value = AuthenticationException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result authenticationExceptionHandler(AuthenticationException e) {
        logger.error("未登录或者无权限");
        return Result.fail(401, e.getMessage());
    }

    /**
     * 未授权异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(value = UnauthorizedException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result unauthorizedExceptionHandler(UnauthorizedException e) {
        logger.error("未登录或者无权限");
        return Result.fail(403, e.getMessage());
    }

}
